package com.hilon.segment.mybatis.utils;

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jose.shaded.json.JSONObject;

import java.security.SecureRandom;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 本项目不使用token.
 * json web tokens.
 * reference: <a href="https://connect2id.com/products/nimbus-jose-jwt/examples/jws-with-hmac">link...</a>
 */
public class JwtUtil {

    public static final byte[] sharedSecret = new byte[32];

    /**
     * 生成token
     *
     * @param payloadMap 用户信息
     * @return 生成的token(字符串)
     * @throws JOSEException 抛出错误.
     */
    public static String createToken(Map<String, Object> payloadMap) throws JOSEException {

        // Generate random 256-bit (32-byte) shared secret
        SecureRandom random = new SecureRandom();
        random.nextBytes(sharedSecret);

        // Create HMAC signer
        JWSSigner signer = new MACSigner(sharedSecret);

        // Prepare JWS object with payloadMap payload
        JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256);
        long TOKEN_EXPIRATION = 24 * 60 * 60 * 1000;
        payloadMap.put("expiration", new Date(System.currentTimeMillis() + TOKEN_EXPIRATION));
        Payload payload = new Payload(new JSONObject(payloadMap));
        JWSObject jwsObject = new JWSObject(jwsHeader, payload);// Apply the HMAC
        jwsObject.sign(signer);

        // To serialize to compact form, produces something like
        // eyJhbGciOiJIUzI1NiJ9.SGVsbG8sIHdvcmxkIQ.onO9Ihudz3WkiauDO2Uhyuz0Y18UASXlSc1eS0NkWyA
        return jwsObject.serialize();
    }

    /**
     * 校验token(简单的示例)
     * @param token 传来的token
     * @return 校验结果
     * @throws ParseException parse jws时抛出
     * @throws JOSEException 校验方法抛出
     */
    public static Map<String, Object> valid(String token) throws ParseException, JOSEException {
        // To parse the JWS and verify it, e.g. on client-side
        JWSObject jwsObject = JWSObject.parse(token);

        Payload payload = jwsObject.getPayload();


        JWSVerifier verifier = new MACVerifier(sharedSecret);

        Map<String, Object> resultMap = new HashMap<>();

        if (jwsObject.verify(verifier)) {
            JSONObject jsonObject = (JSONObject) payload.toJSONObject();
            resultMap.put("data", jsonObject);
            resultMap.put("result", 0);
            if (jsonObject.containsKey("expiration")) {
                Long expTime = (Long) jsonObject.get("expiration");
                Long nowTime = new Date().getTime();
                resultMap.put("result", expTime > nowTime ? 0 : 2);
            }
            // 还可以添加是否过期等校验...
        } else {
            resultMap.put("result", 1);
        }
        return resultMap;
    }
}
